package com.hsq.ndmall.user.controller;

import java.text.ParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;

//import org.apache.shiro.authz.annotation.RequiresPermissions;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hsq.ndmall.common.utils.IpUtils;
import com.hsq.ndmall.common.utils.ListFromEntity2VoUtils;
import com.hsq.ndmall.user.config.WxMaConfiguration;
import com.hsq.ndmall.user.config.WxMaProperties;
import com.hsq.ndmall.user.dto.UserInfo;
import com.hsq.ndmall.user.feign.Oauth2Feign;
import com.nimbusds.jose.JWSObject;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.ApiOperation;
import com.hsq.ndmall.user.entity.MemberEntity;
import com.hsq.ndmall.user.service.MemberService;
import com.hsq.ndmall.common.utils.PageUtils;
import com.hsq.ndmall.common.utils.R;
import io.swagger.annotations.Api;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;


/**
 * 会员表
 *
 * @author Mr.Huang
 * @email 1607922199@qq.com
 * @date 2021-08-19 15:04:51
 */
@Api(tags = "MemberController", description = "会员表 服务")
@RestController
@RequestMapping("user/member")
@Slf4j
public class MemberController {
    @Autowired
    private MemberService memberService;

    @Autowired
    WxMaProperties wxMaProperties;

    @Autowired
    Oauth2Feign oauth2Feign;

    /**
     * 列表
     */
    @GetMapping("/list")
    //@RequiresPermissions("user:member:list")
    @ApiOperation("获取所有会员表 信息")
    public R list(@RequestParam Map<String, Object> params) {
        PageUtils page = memberService.queryPage(params);

        return R.ok().put("page", page);
    }


    /**
     * 信息
     */
    @GetMapping("/info/{id}")
    //@RequiresPermissions("user:member:info")
    @ApiOperation("获取指定id的会员表 详情")
    public R info(@PathVariable("id") Integer id) {
        MemberEntity member = memberService.getById(id);

        return R.ok().put("member", member);
    }

    /**
     * 保存
     */
    @PostMapping("/save")
    @ApiOperation("添加会员表 信息")
    //@RequiresPermissions("user:member:save")
    public R save(@RequestBody MemberEntity member) {
        memberService.save(member);

        return R.ok();
    }

    /**
     * 修改
     */
    @PutMapping("/update")
    @ApiOperation("更新指定id会员表 信息")
    //@RequiresPermissions("user:member:update")
    public R update(@RequestBody MemberEntity member) {
        memberService.updateById(member);

        return R.ok();
    }

    /**
     * 删除
     */
    @DeleteMapping("/delete")
    @ApiOperation("删除指定id会员表 信息")
    //@RequiresPermissions("user:member:delete")
    public R delete(@RequestBody Integer[] ids) {
        memberService.removeByIds(Arrays.asList(ids));

        return R.ok();
    }

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 由wx/auth/* 路由到 user/member/* 下
     * TODO 登录
     *
     * @param map
     * @param httpServletRequest
     * @return
     */
    @PostMapping("login_by_weixin")
    public R getToken(@RequestBody Map<String, Object> map, HttpServletRequest httpServletRequest) {
        // 1、获取code参数值
        String code = (String) map.get("code");
        UserInfo userInfo = MapUtil.get(map, "userInfo", UserInfo.class);
        String appid = this.wxMaProperties.getConfigs().get(0).getAppid();
        String client_id = (String) map.get("client_id");
        String client_secret = (String) map.get("client_secret");
        System.out.println(client_id + "======================" + client_secret);
        // 2、验证appid的有效期
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
        // 3 、openId
        String openId = null;
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
            log.info(session.getSessionKey());
            log.info(session.getOpenid());
            openId = session.getOpenid();
            //TODO 可以增加自己的逻辑，关联业务相关数据
            if (session.getSessionKey() != null && openId != null) {
                // 走数据库查询微信用户是否注册   Openid
                HashMap<String, Object> param = MapUtil.newHashMap();
                param.put("wx_openid", session.getOpenid());
                List<MemberEntity> member = (List<MemberEntity>) memberService.queryPage(param).getList();
                if (member == null || member.size() == 0) {
                    // 数据库没有,把数据存放到数据库
                    MemberEntity memberDto = new MemberEntity();
                    memberDto.setId(null);
                    memberDto.setAddTime(new Date());
                    memberDto.setUsername(openId);
                    memberDto.setPassword(passwordEncoder.encode(openId));
                    memberDto.setGender(userInfo.getGender());
                    memberDto.setLastLoginTime(new Date());
                    memberDto.setMobile("17373674939");
                    memberDto.setAvatar(userInfo.getAvatarUrl());
                    memberDto.setWeixinOpenid(openId);
                    memberDto.setSessionKey(session.getSessionKey());
                    memberDto.setStatus(0);
                    memberDto.setDeleted(false);
                    memberDto.setLastLoginIp(IpUtils.getIpAddr(httpServletRequest));
                    memberDto.setNickname(userInfo.getNickName());
                    this.save(memberDto);
                } else {
                    // 数据库有  去更新
                    //List<Map> list = MapUtil.get((Map) member.get("page"), "list", List.class);
                    //List<Map> memberList = MapUtil.get(member.get("page"), "list", List.class);
//                    List<Map> mapList = (List<Map>) ((Map)member.get("page")).get("list");
//                    List<MemberEntity> memberEntities = ListFromEntity2VoUtils.entity2Vo(mapList, MemberEntity.class);
                    MemberEntity memberEntity = member.get(0);
                    MemberEntity memberDto = new MemberEntity();
                    memberDto.setId(memberEntity.getId());
                    memberDto.setNickname(userInfo.getNickName());
                    memberDto.setGender(userInfo.getGender());
                    memberDto.setSessionKey(session.getSessionKey());
                    memberDto.setUpdateTime(new Date());
                    memberDto.setLastLoginTime(new Date());
                    memberDto.setAvatar(userInfo.getAvatarUrl());
                    memberDto.setLastLoginIp(IpUtils.getIpAddr(httpServletRequest));
                    this.update(memberDto);
                }
            } else {
                R.error();
            }
            // Grafana、Prometheus、Exporter  Thread PoolExecutor  CompletableFuture   Myisam
            //FULLTEXT NORMAL SPATIAL UNIQUE explain  between
            // 生成JWT  发送凭证，远程调认证服务，让他去生成token
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("grant_type", "password");
//            paramMap.put("client_id", "client-app");
//            paramMap.put("client_secret", "123456");
            paramMap.put("username", openId);
            paramMap.put("password", openId);
            paramMap.put("client_id", client_id);
            paramMap.put("client_secret", client_secret);
            R token = oauth2Feign.postAccessToken(paramMap);
            String JWTToken = (String) token.get("token");
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("token", JWTToken);
            resultMap.put("refresh_token",token.get("refreshToken"));
            resultMap.put("userInfo", userInfo);
            return R.ok().put("data", resultMap);
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
        }
        return R.ok();
    }


    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 登出
     *
     * @param request
     * @return
     */
    @PostMapping("logout")
    public R getOutLogin(HttpServletRequest request) {
        try {
            String JWTToken = request.getHeader("Authorization");
            JWTToken = JWTToken.replace("Bearer", Strings.EMPTY);
            System.out.println(JWTToken + "=========================第一步");
            JWSObject parse = JWSObject.parse(JWTToken);
            String payload = parse.getPayload().toString();

            JSONObject jsonObject = JSONUtil.parseObj(payload);
            String jti = jsonObject.getStr("jti");   // 获取JWT的唯一标识jti
            Long exp = jsonObject.getLong("exp");  // JWT的过期时间（秒）
            long currentTimeSeconds = System.currentTimeMillis() / 1000;  // 获取当前系统的时间
            if (exp < currentTimeSeconds) {   // token 已过期
                return R.unauthorized("您的token已过期~~~");
            }
            // 保存到redis中
            redisTemplate.opsForValue().set("jwt::" + jti, null, (exp - currentTimeSeconds), TimeUnit.SECONDS);
            return R.ok();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return R.ok();
    }

    @PostMapping("regCaptcha")
    public R verificationCode(@RequestParam String mobile){

        return R.ok();
    }
}
